home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / tcltk / tk8.4 / console.tcl < prev    next >
Text File  |  2009-04-29  |  27KB  |  959 lines

  1. # console.tcl --
  2. #
  3. # This code constructs the console window for an application.  It
  4. # can be used by non-unix systems that do not have built-in support
  5. # for shells.
  6. #
  7. # RCS: @(#) $Id: console.tcl,v 1.22.2.7 2007/11/09 07:08:51 das Exp $
  8. #
  9. # Copyright (c) 1995-1997 Sun Microsystems, Inc.
  10. # Copyright (c) 1998-2000 Ajuba Solutions.
  11. # Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
  12. #
  13. # See the file "license.terms" for information on usage and redistribution
  14. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  15. #
  16.  
  17. # TODO: history - remember partially written command
  18.  
  19. namespace eval ::tk::console {
  20.     variable blinkTime   500 ; # msecs to blink braced range for
  21.     variable blinkRange  1   ; # enable blinking of the entire braced range
  22.     variable magicKeys   1   ; # enable brace matching and proc/var recognition
  23.     variable maxLines    600 ; # maximum # of lines buffered in console
  24.     variable showMatches 1   ; # show multiple expand matches
  25.  
  26.     variable inPlugin [info exists embed_args]
  27.     variable defaultPrompt  ; # default prompt if tcl_prompt1 isn't used
  28.  
  29.  
  30.     if {$inPlugin} {
  31.     set defaultPrompt {subst {[history nextid] % }}
  32.     } else {
  33.     set defaultPrompt {subst {([file tail [pwd]]) [history nextid] % }}
  34.     }
  35. }
  36.  
  37. # simple compat function for tkcon code added for this console
  38. interp alias {} EvalAttached {} consoleinterp eval
  39.  
  40. # ::tk::ConsoleInit --
  41. # This procedure constructs and configures the console windows.
  42. #
  43. # Arguments:
  44. #     None.
  45.  
  46. proc ::tk::ConsoleInit {} {
  47.     global tcl_platform
  48.  
  49.     if {![consoleinterp eval {set tcl_interactive}]} {
  50.     wm withdraw .
  51.     }
  52.  
  53.     if {$tcl_platform(platform) eq "macintosh"
  54.         || [tk windowingsystem] eq "aqua"} {
  55.     set mod "Cmd"
  56.     } else {
  57.     set mod "Ctrl"
  58.     }
  59.  
  60.     if {[catch {menu .menubar} err]} { bgerror "INIT: $err" }
  61.     .menubar add cascade -label File -menu .menubar.file -underline 0
  62.     .menubar add cascade -label Edit -menu .menubar.edit -underline 0
  63.  
  64.     menu .menubar.file -tearoff 0
  65.     .menubar.file add command -label [mc "Source..."] \
  66.         -underline 0 -command tk::ConsoleSource
  67.     .menubar.file add command -label [mc "Hide Console"] \
  68.         -underline 0 -command {wm withdraw .}
  69.     .menubar.file add command -label [mc "Clear Console"] \
  70.         -underline 0 -command {.console delete 1.0 "promptEnd linestart"}
  71.    if {$tcl_platform(platform) eq "macintosh"
  72.         || [tk windowingsystem] eq "aqua"} {
  73.     .menubar.file add command -label [mc "Quit"] \
  74.         -command exit -accel Cmd-Q
  75.     } else {
  76.     .menubar.file add command -label [mc "Exit"] \
  77.         -underline 1 -command exit
  78.     }
  79.  
  80.     menu .menubar.edit -tearoff 0
  81.     .menubar.edit add command -label [mc "Cut"] -underline 2 \
  82.         -command { event generate .console <<Cut>> } -accel "$mod+X"
  83.     .menubar.edit add command -label [mc "Copy"] -underline 0 \
  84.         -command { event generate .console <<Copy>> } -accel "$mod+C"
  85.     .menubar.edit add command -label [mc "Paste"] -underline 1 \
  86.         -command { event generate .console <<Paste>> } -accel "$mod+V"
  87.  
  88.     if {$tcl_platform(platform) ne "windows"} {
  89.     .menubar.edit add command -label [mc "Clear"] -underline 2 \
  90.         -command { event generate .console <<Clear>> }
  91.     } else {
  92.     .menubar.edit add command -label [mc "Delete"] -underline 0 \
  93.         -command { event generate .console <<Clear>> } -accel "Del"
  94.     
  95.     .menubar add cascade -label Help -menu .menubar.help -underline 0
  96.     menu .menubar.help -tearoff 0
  97.     .menubar.help add command -label [mc "About..."] \
  98.         -underline 0 -command tk::ConsoleAbout
  99.     }
  100.  
  101.     . configure -menu .menubar
  102.  
  103.     set con [text .console  -yscrollcommand [list .sb set] -setgrid true]
  104.     scrollbar .sb -command [list $con yview]
  105.     pack .sb -side right -fill both
  106.     pack $con -fill both -expand 1 -side left
  107.     switch -exact $tcl_platform(platform) {
  108.     "macintosh" {
  109.         $con configure -font {Monaco 10 normal} -highlightthickness 0
  110.     }
  111.     "windows" {
  112.         $con configure -font systemfixed
  113.     }
  114.     "unix" {
  115.         if {[tk windowingsystem] eq "aqua"} {
  116.         $con configure -font {Monaco 10 normal} -highlightthickness 0
  117.         }
  118.     }
  119.     }
  120.  
  121.     ConsoleBind $con
  122.  
  123.     $con tag configure stderr    -foreground red
  124.     $con tag configure stdin    -foreground blue
  125.     $con tag configure prompt    -foreground \#8F4433
  126.     $con tag configure proc    -foreground \#008800
  127.     $con tag configure var    -background \#FFC0D0
  128.     $con tag raise sel
  129.     $con tag configure blink    -background \#FFFF00
  130.     $con tag configure find    -background \#FFFF00
  131.  
  132.     focus $con
  133.  
  134.     wm protocol . WM_DELETE_WINDOW { wm withdraw . }
  135.     wm title . [mc "Console"]
  136.     flush stdout
  137.     $con mark set output [$con index "end - 1 char"]
  138.     tk::TextSetCursor $con end
  139.     $con mark set promptEnd insert
  140.     $con mark gravity promptEnd left
  141.  
  142.     # A variant of ConsolePrompt to avoid a 'puts' call
  143.     set w $con
  144.     set temp [$w index "end - 1 char"]
  145.     $w mark set output end
  146.     if {![consoleinterp eval "info exists tcl_prompt1"]} {
  147.     set string [EvalAttached $::tk::console::defaultPrompt]
  148.     $w insert output $string stdout
  149.     }
  150.     $w mark set output $temp
  151.     ::tk::TextSetCursor $w end
  152.     $w mark set promptEnd insert
  153.     $w mark gravity promptEnd left
  154.  
  155.     if {$tcl_platform(platform) eq "windows"} {
  156.     # Subtle work-around to erase the '% ' that tclMain.c prints out
  157.     after idle [subst -nocommand {
  158.         if {[$con get 1.0 output] eq "% "} { $con delete 1.0 output }
  159.     }]
  160.     }
  161. }
  162.  
  163. # ::tk::ConsoleSource --
  164. #
  165. # Prompts the user for a file to source in the main interpreter.
  166. #
  167. # Arguments:
  168. # None.
  169.  
  170. proc ::tk::ConsoleSource {} {
  171.     set filename [tk_getOpenFile -defaultextension .tcl -parent . \
  172.         -title [mc "Select a file to source"] \
  173.         -filetypes [list \
  174.         [list [mc "Tcl Scripts"] .tcl] \
  175.         [list [mc "All Files"] *]]]
  176.     if {$filename ne ""} {
  177.         set cmd [list source $filename]
  178.     if {[catch {consoleinterp eval $cmd} result]} {
  179.         ConsoleOutput stderr "$result\n"
  180.     }
  181.     }
  182. }
  183.  
  184. # ::tk::ConsoleInvoke --
  185. # Processes the command line input.  If the command is complete it
  186. # is evaled in the main interpreter.  Otherwise, the continuation
  187. # prompt is added and more input may be added.
  188. #
  189. # Arguments:
  190. # None.
  191.  
  192. proc ::tk::ConsoleInvoke {args} {
  193.     set ranges [.console tag ranges input]
  194.     set cmd ""
  195.     if {[llength $ranges]} {
  196.     set pos 0
  197.     while {[lindex $ranges $pos] ne ""} {
  198.         set start [lindex $ranges $pos]
  199.         set end [lindex $ranges [incr pos]]
  200.         append cmd [.console get $start $end]
  201.         incr pos
  202.     }
  203.     }
  204.     if {$cmd eq ""} {
  205.     ConsolePrompt
  206.     } elseif {[info complete $cmd]} {
  207.     .console mark set output end
  208.     .console tag delete input
  209.     set result [consoleinterp record $cmd]
  210.     if {$result ne ""} {
  211.         puts $result
  212.     }
  213.     ConsoleHistory reset
  214.     ConsolePrompt
  215.     } else {
  216.     ConsolePrompt partial
  217.     }
  218.     .console yview -pickplace insert
  219. }
  220.  
  221. # ::tk::ConsoleHistory --
  222. # This procedure implements command line history for the
  223. # console.  In general is evals the history command in the
  224. # main interpreter to obtain the history.  The variable
  225. # ::tk::HistNum is used to store the current location in the history.
  226. #
  227. # Arguments:
  228. # cmd -    Which action to take: prev, next, reset.
  229.  
  230. set ::tk::HistNum 1
  231. proc ::tk::ConsoleHistory {cmd} {
  232.     variable HistNum
  233.  
  234.     switch $cmd {
  235.         prev {
  236.         incr HistNum -1
  237.         if {$HistNum == 0} {
  238.         set cmd {history event [expr {[history nextid] -1}]}
  239.         } else {
  240.         set cmd "history event $HistNum"
  241.         }
  242.             if {[catch {consoleinterp eval $cmd} cmd]} {
  243.                 incr HistNum
  244.                 return
  245.             }
  246.         .console delete promptEnd end
  247.             .console insert promptEnd $cmd {input stdin}
  248.         }
  249.         next {
  250.         incr HistNum
  251.         if {$HistNum == 0} {
  252.         set cmd {history event [expr {[history nextid] -1}]}
  253.         } elseif {$HistNum > 0} {
  254.         set cmd ""
  255.         set HistNum 1
  256.         } else {
  257.         set cmd "history event $HistNum"
  258.         }
  259.         if {$cmd ne ""} {
  260.         catch {consoleinterp eval $cmd} cmd
  261.         }
  262.         .console delete promptEnd end
  263.         .console insert promptEnd $cmd {input stdin}
  264.         }
  265.         reset {
  266.             set HistNum 1
  267.         }
  268.     }
  269. }
  270.  
  271. # ::tk::ConsolePrompt --
  272. # This procedure draws the prompt.  If tcl_prompt1 or tcl_prompt2
  273. # exists in the main interpreter it will be called to generate the 
  274. # prompt.  Otherwise, a hard coded default prompt is printed.
  275. #
  276. # Arguments:
  277. # partial -    Flag to specify which prompt to print.
  278.  
  279. proc ::tk::ConsolePrompt {{partial normal}} {
  280.     set w .console
  281.     if {$partial eq "normal"} {
  282.     set temp [$w index "end - 1 char"]
  283.     $w mark set output end
  284.         if {[consoleinterp eval "info exists tcl_prompt1"]} {
  285.             consoleinterp eval "eval \[set tcl_prompt1\]"
  286.         } else {
  287.             puts -nonewline [EvalAttached $::tk::console::defaultPrompt]
  288.         }
  289.     } else {
  290.     set temp [$w index output]
  291.     $w mark set output end
  292.         if {[consoleinterp eval "info exists tcl_prompt2"]} {
  293.             consoleinterp eval "eval \[set tcl_prompt2\]"
  294.         } else {
  295.         puts -nonewline "> "
  296.         }
  297.     }
  298.     flush stdout
  299.     $w mark set output $temp
  300.     ::tk::TextSetCursor $w end
  301.     $w mark set promptEnd insert
  302.     $w mark gravity promptEnd left
  303.     ::tk::console::ConstrainBuffer $w $::tk::console::maxLines
  304.     $w see end
  305. }
  306.  
  307. # ::tk::ConsoleBind --
  308. # This procedure first ensures that the default bindings for the Text
  309. # class have been defined.  Then certain bindings are overridden for
  310. # the class.
  311. #
  312. # Arguments:
  313. # None.
  314.  
  315. proc ::tk::ConsoleBind {w} {
  316.     bindtags $w [list $w Console PostConsole [winfo toplevel $w] all]
  317.  
  318.     ## Get all Text bindings into Console
  319.     foreach ev [bind Text] { bind Console $ev [bind Text $ev] }    
  320.     ## We really didn't want the newline insertion...
  321.     bind Console <Control-Key-o> {}
  322.     ## ...or any Control-v binding (would block <<Paste>>)
  323.     bind Console <Control-Key-v> {}
  324.  
  325.     # For the moment, transpose isn't enabled until the console
  326.     # gets and overhaul of how it handles input -- hobbs
  327.     bind Console <Control-Key-t> {}
  328.  
  329.     # Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
  330.     # Otherwise, if a widget binding for one of these is defined, the
  331.  
  332.     bind Console <Alt-KeyPress> {# nothing }
  333.     bind Console <Meta-KeyPress> {# nothing}
  334.     bind Console <Control-KeyPress> {# nothing}
  335.  
  336.     foreach {ev key} {
  337.     <<Console_Prev>>        <Key-Up>
  338.     <<Console_Next>>        <Key-Down>
  339.     <<Console_NextImmediate>>    <Control-Key-n>
  340.     <<Console_PrevImmediate>>    <Control-Key-p>
  341.     <<Console_PrevSearch>>        <Control-Key-r>
  342.     <<Console_NextSearch>>        <Control-Key-s>
  343.  
  344.     <<Console_Expand>>        <Key-Tab>
  345.     <<Console_Expand>>        <Key-Escape>
  346.     <<Console_ExpandFile>>        <Control-Shift-Key-F>
  347.     <<Console_ExpandProc>>        <Control-Shift-Key-P>
  348.     <<Console_ExpandVar>>        <Control-Shift-Key-V>
  349.     <<Console_Tab>>            <Control-Key-i>
  350.     <<Console_Tab>>            <Meta-Key-i>
  351.     <<Console_Eval>>        <Key-Return>
  352.     <<Console_Eval>>        <Key-KP_Enter>
  353.  
  354.     <<Console_Clear>>        <Control-Key-l>
  355.     <<Console_KillLine>>        <Control-Key-k>
  356.     <<Console_Transpose>>        <Control-Key-t>
  357.     <<Console_ClearLine>>        <Control-Key-u>
  358.     <<Console_SaveCommand>>        <Control-Key-z>
  359.     } {
  360.     event add $ev $key
  361.     bind Console $key {}
  362.     }
  363.  
  364.     bind Console <<Console_Expand>> {
  365.     if {[%W compare insert > promptEnd]} {::tk::console::Expand %W}
  366.     }
  367.     bind Console <<Console_ExpandFile>> {
  368.     if {[%W compare insert > promptEnd]} {::tk::console::Expand %W path}
  369.     }
  370.     bind Console <<Console_ExpandProc>> {
  371.     if {[%W compare insert > promptEnd]} {::tk::console::Expand %W proc}
  372.     }
  373.     bind Console <<Console_ExpandVar>> {
  374.     if {[%W compare insert > promptEnd]} {::tk::console::Expand %W var}
  375.     }
  376.     bind Console <<Console_Eval>> {
  377.     %W mark set insert {end - 1c}
  378.     tk::ConsoleInsert %W "\n"
  379.     tk::ConsoleInvoke
  380.     break
  381.     }
  382.     bind Console <Delete> {
  383.     if {[%W tag nextrange sel 1.0 end] ne "" && [%W compare sel.first >= promptEnd]} {
  384.         %W delete sel.first sel.last
  385.     } elseif {[%W compare insert >= promptEnd]} {
  386.         %W delete insert
  387.         %W see insert
  388.     }
  389.     }
  390.     bind Console <BackSpace> {
  391.     if {[%W tag nextrange sel 1.0 end] ne "" && [%W compare sel.first >= promptEnd]} {
  392.         %W delete sel.first sel.last
  393.     } elseif {[%W compare insert != 1.0] && \
  394.         [%W compare insert > promptEnd]} {
  395.         %W delete insert-1c
  396.         %W see insert
  397.     }
  398.     }
  399.     bind Console <Control-h> [bind Console <BackSpace>]
  400.  
  401.     bind Console <Home> {
  402.     if {[%W compare insert < promptEnd]} {
  403.         tk::TextSetCursor %W {insert linestart}
  404.     } else {
  405.         tk::TextSetCursor %W promptEnd
  406.     }
  407.     }
  408.     bind Console <Control-a> [bind Console <Home>]
  409.     bind Console <End> {
  410.     tk::TextSetCursor %W {insert lineend}
  411.     }
  412.     bind Console <Control-e> [bind Console <End>]
  413.     bind Console <Control-d> {
  414.     if {[%W compare insert < promptEnd]} break
  415.     %W delete insert
  416.     }
  417.     bind Console <<Console_KillLine>> {
  418.     if {[%W compare insert < promptEnd]} break
  419.     if {[%W compare insert == {insert lineend}]} {
  420.         %W delete insert
  421.     } else {
  422.         %W delete insert {insert lineend}
  423.     }
  424.     }
  425.     bind Console <<Console_Clear>> {
  426.     ## Clear console display
  427.     %W delete 1.0 "promptEnd linestart"
  428.     }
  429.     bind Console <<Console_ClearLine>> {
  430.     ## Clear command line (Unix shell staple)
  431.     %W delete promptEnd end
  432.     }
  433.     bind Console <Meta-d> {
  434.     if {[%W compare insert >= promptEnd]} {
  435.         %W delete insert {insert wordend}
  436.     }
  437.     }
  438.     bind Console <Meta-BackSpace> {
  439.     if {[%W compare {insert -1c wordstart} >= promptEnd]} {
  440.         %W delete {insert -1c wordstart} insert
  441.     }
  442.     }
  443.     bind Console <Meta-d> {
  444.     if {[%W compare insert >= promptEnd]} {
  445.         %W delete insert {insert wordend}
  446.     }
  447.     }
  448.     bind Console <Meta-BackSpace> {
  449.     if {[%W compare {insert -1c wordstart} >= promptEnd]} {
  450.         %W delete {insert -1c wordstart} insert
  451.     }
  452.     }
  453.     bind Console <Meta-Delete> {
  454.     if {[%W compare insert >= promptEnd]} {
  455.         %W delete insert {insert wordend}
  456.     }
  457.     }
  458.     bind Console <<Console_Prev>> {
  459.     tk::ConsoleHistory prev
  460.     }
  461.     bind Console <<Console_Next>> {
  462.     tk::ConsoleHistory next
  463.     }
  464.     bind Console <Insert> {
  465.     catch {tk::ConsoleInsert %W [::tk::GetSelection %W PRIMARY]}
  466.     }
  467.     bind Console <KeyPress> {
  468.     tk::ConsoleInsert %W %A
  469.     }
  470.     bind Console <F9> {
  471.     eval destroy [winfo child .]
  472.     if {$tcl_platform(platform) eq "macintosh"} {
  473.         if {[catch {source [file join $tk_library console.tcl]}]} {source -rsrc console}
  474.     } else {
  475.         source [file join $tk_library console.tcl]
  476.     }
  477.     }
  478.     if {$::tcl_platform(platform) eq "macintosh" || [tk windowingsystem] eq "aqua"} {
  479.         bind Console <Command-q> {
  480.         exit
  481.         }
  482.     }
  483.     bind Console <<Cut>> {
  484.         # Same as the copy event
  485.      if {![catch {set data [%W get sel.first sel.last]}]} {
  486.         clipboard clear -displayof %W
  487.         clipboard append -displayof %W $data
  488.     }
  489.     }
  490.     bind Console <<Copy>> {
  491.      if {![catch {set data [%W get sel.first sel.last]}]} {
  492.         clipboard clear -displayof %W
  493.         clipboard append -displayof %W $data
  494.     }
  495.     }
  496.     bind Console <<Paste>> {
  497.     catch {
  498.         set clip [::tk::GetSelection %W CLIPBOARD]
  499.         set list [split $clip \n\r]
  500.         tk::ConsoleInsert %W [lindex $list 0]
  501.         foreach x [lrange $list 1 end] {
  502.         %W mark set insert {end - 1c}
  503.         tk::ConsoleInsert %W "\n"
  504.         tk::ConsoleInvoke
  505.         tk::ConsoleInsert %W $x
  506.         }
  507.     }
  508.     }
  509.  
  510.     ##
  511.     ## Bindings for doing special things based on certain keys
  512.     ##
  513.     bind PostConsole <Key-parenright> {
  514.     if {"\\" ne [%W get insert-2c]} {
  515.         ::tk::console::MatchPair %W \( \) promptEnd
  516.     }
  517.     }
  518.     bind PostConsole <Key-bracketright> {
  519.     if {"\\" ne [%W get insert-2c]} {
  520.         ::tk::console::MatchPair %W \[ \] promptEnd
  521.     }
  522.     }
  523.     bind PostConsole <Key-braceright> {
  524.     if {"\\" ne [%W get insert-2c]} {
  525.         ::tk::console::MatchPair %W \{ \} promptEnd
  526.     }
  527.     }
  528.     bind PostConsole <Key-quotedbl> {
  529.     if {"\\" ne [%W get insert-2c]} {
  530.         ::tk::console::MatchQuote %W promptEnd
  531.     }
  532.     }
  533.  
  534.     bind PostConsole <KeyPress> {
  535.     if {"%A" ne ""} {
  536.         ::tk::console::TagProc %W
  537.     }
  538.     break
  539.     }
  540. }
  541.  
  542. # ::tk::ConsoleInsert --
  543. # Insert a string into a text at the point of the insertion cursor.
  544. # If there is a selection in the text, and it covers the point of the
  545. # insertion cursor, then delete the selection before inserting.  Insertion
  546. # is restricted to the prompt area.
  547. #
  548. # Arguments:
  549. # w -        The text window in which to insert the string
  550. # s -        The string to insert (usually just a single character)
  551.  
  552. proc ::tk::ConsoleInsert {w s} {
  553.     if {$s eq ""} {
  554.     return
  555.     }
  556.     catch {
  557.     if {[$w compare sel.first <= insert]
  558.         && [$w compare sel.last >= insert]} {
  559.         $w tag remove sel sel.first promptEnd
  560.         $w delete sel.first sel.last
  561.     }
  562.     }
  563.     if {[$w compare insert < promptEnd]} {
  564.     $w mark set insert end
  565.     }
  566.     $w insert insert $s {input stdin}
  567.     $w see insert
  568. }
  569.  
  570. # ::tk::ConsoleOutput --
  571. #
  572. # This routine is called directly by ConsolePutsCmd to cause a string
  573. # to be displayed in the console.
  574. #
  575. # Arguments:
  576. # dest -    The output tag to be used: either "stderr" or "stdout".
  577. # string -    The string to be displayed.
  578.  
  579. proc ::tk::ConsoleOutput {dest string} {
  580.     set w .console
  581.     $w insert output $string $dest
  582.     ::tk::console::ConstrainBuffer $w $::tk::console::maxLines
  583.     $w see insert
  584. }
  585.  
  586. # ::tk::ConsoleExit --
  587. #
  588. # This routine is called by ConsoleEventProc when the main window of
  589. # the application is destroyed.  Don't call exit - that probably already
  590. # happened.  Just delete our window.
  591. #
  592. # Arguments:
  593. # None.
  594.  
  595. proc ::tk::ConsoleExit {} {
  596.     destroy .
  597. }
  598.  
  599. # ::tk::ConsoleAbout --
  600. #
  601. # This routine displays an About box to show Tcl/Tk version info.
  602. #
  603. # Arguments:
  604. # None.
  605.  
  606. proc ::tk::ConsoleAbout {} {
  607.     tk_messageBox -type ok -message "[mc {Tcl for Windows}]
  608.  
  609. Tcl $::tcl_patchLevel
  610. Tk $::tk_patchLevel"
  611. }
  612.  
  613. # ::tk::console::TagProc --
  614. #
  615. # Tags a procedure in the console if it's recognized
  616. # This procedure is not perfect.  However, making it perfect wastes
  617. # too much CPU time...
  618. #
  619. # Arguments:
  620. #    w    - console text widget
  621.  
  622. proc ::tk::console::TagProc w {
  623.     if {!$::tk::console::magicKeys} { return }
  624.     set exp "\[^\\\\\]\[\[ \t\n\r\;{}\"\$\]"
  625.     set i [$w search -backwards -regexp $exp insert-1c promptEnd-1c]
  626.     if {$i eq ""} {set i promptEnd} else {append i +2c}
  627.     regsub -all "\[\[\\\\\\?\\*\]" [$w get $i "insert-1c wordend"] {\\\0} c
  628.     if {[llength [EvalAttached [list info commands $c]]]} {
  629.     $w tag add proc $i "insert-1c wordend"
  630.     } else {
  631.     $w tag remove proc $i "insert-1c wordend"
  632.     }
  633.     if {[llength [EvalAttached [list info vars $c]]]} {
  634.     $w tag add var $i "insert-1c wordend"
  635.     } else {
  636.     $w tag remove var $i "insert-1c wordend"
  637.     }
  638. }
  639.  
  640. # ::tk::console::MatchPair --
  641. #
  642. # Blinks a matching pair of characters
  643. # c2 is assumed to be at the text index 'insert'.
  644. # This proc is really loopy and took me an hour to figure out given
  645. # all possible combinations with escaping except for escaped \'s.
  646. # It doesn't take into account possible commenting... Oh well.  If
  647. # anyone has something better, I'd like to see/use it.  This is really
  648. # only efficient for small contexts.
  649. #
  650. # Arguments:
  651. #    w    - console text widget
  652. #     c1    - first char of pair
  653. #     c2    - second char of pair
  654. #
  655. # Calls:    ::tk::console::Blink
  656.  
  657. proc ::tk::console::MatchPair {w c1 c2 {lim 1.0}} {
  658.     if {!$::tk::console::magicKeys} { return }
  659.     if {[set ix [$w search -back $c1 insert $lim]] ne ""} {
  660.     while {
  661.         [string match {\\} [$w get $ix-1c]] &&
  662.         [set ix [$w search -back $c1 $ix-1c $lim]] ne ""
  663.     } {}
  664.     set i1 insert-1c
  665.     while {$ix ne ""} {
  666.         set i0 $ix
  667.         set j 0
  668.         while {[set i0 [$w search $c2 $i0 $i1]] ne ""} {
  669.         append i0 +1c
  670.         if {[string match {\\} [$w get $i0-2c]]} continue
  671.         incr j
  672.         }
  673.         if {!$j} break
  674.         set i1 $ix
  675.         while {$j && [set ix [$w search -back $c1 $ix $lim]] ne ""} {
  676.         if {[string match {\\} [$w get $ix-1c]]} continue
  677.         incr j -1
  678.         }
  679.     }
  680.     if {[string match {} $ix]} { set ix [$w index $lim] }
  681.     } else { set ix [$w index $lim] }
  682.     if {$::tk::console::blinkRange} {
  683.     Blink $w $ix [$w index insert]
  684.     } else {
  685.     Blink $w $ix $ix+1c [$w index insert-1c] [$w index insert]
  686.     }
  687. }
  688.  
  689. # ::tk::console::MatchQuote --
  690. #
  691. # Blinks between matching quotes.
  692. # Blinks just the quote if it's unmatched, otherwise blinks quoted string
  693. # The quote to match is assumed to be at the text index 'insert'.
  694. #
  695. # Arguments:
  696. #    w    - console text widget
  697. #
  698. # Calls:    ::tk::console::Blink
  699.  
  700. proc ::tk::console::MatchQuote {w {lim 1.0}} {
  701.     if {!$::tk::console::magicKeys} { return }
  702.     set i insert-1c
  703.     set j 0
  704.     while {[set i [$w search -back \" $i $lim]] ne ""} {
  705.     if {[string match {\\} [$w get $i-1c]]} continue
  706.     if {!$j} {set i0 $i}
  707.     incr j
  708.     }
  709.     if {$j&1} {
  710.     if {$::tk::console::blinkRange} {
  711.         Blink $w $i0 [$w index insert]
  712.     } else {
  713.         Blink $w $i0 $i0+1c [$w index insert-1c] [$w index insert]
  714.     }
  715.     } else {
  716.     Blink $w [$w index insert-1c] [$w index insert]
  717.     }
  718. }
  719.  
  720. # ::tk::console::Blink --
  721. #
  722. # Blinks between n index pairs for a specified duration.
  723. #
  724. # Arguments:
  725. #    w    - console text widget
  726. #     i1    - start index to blink region
  727. #     i2    - end index of blink region
  728. #     dur    - duration in usecs to blink for
  729. #
  730. # Outputs:
  731. #    blinks selected characters in $w
  732.  
  733. proc ::tk::console::Blink {w args} {
  734.     eval [list $w tag add blink] $args
  735.     after $::tk::console::blinkTime [list $w] tag remove blink $args
  736. }
  737.  
  738. # ::tk::console::ConstrainBuffer --
  739. #
  740. # This limits the amount of data in the text widget
  741. # Called by Prompt and ConsoleOutput
  742. #
  743. # Arguments:
  744. #    w    - console text widget
  745. #    size    - # of lines to constrain to
  746. #
  747. # Outputs:
  748. #    may delete data in console widget
  749.  
  750. proc ::tk::console::ConstrainBuffer {w size} {
  751.     if {[$w index end] > $size} {
  752.     $w delete 1.0 [expr {int([$w index end])-$size}].0
  753.     }
  754. }
  755.  
  756. # ::tk::console::Expand --
  757. #
  758. # Arguments:
  759. # ARGS:    w    - text widget in which to expand str
  760. #     type    - type of expansion (path / proc / variable)
  761. #
  762. # Calls:    ::tk::console::Expand(Pathname|Procname|Variable)
  763. #
  764. # Outputs:    The string to match is expanded to the longest possible match.
  765. #        If ::tk::console::showMatches is non-zero and the longest match
  766. #        equaled the string to expand, then all possible matches are
  767. #        output to stdout.  Triggers bell if no matches are found.
  768. #
  769. # Returns:    number of matches found
  770.  
  771. proc ::tk::console::Expand {w {type ""}} {
  772.     set exp "\[^\\\\\]\[\[ \t\n\r\\\{\"\\\\\$\]"
  773.     set tmp [$w search -backwards -regexp $exp insert-1c promptEnd-1c]
  774.     if {$tmp eq ""} {set tmp promptEnd} else {append tmp +2c}
  775.     if {[$w compare $tmp >= insert]} { return }
  776.     set str [$w get $tmp insert]
  777.     switch -glob $type {
  778.     path* { set res [ExpandPathname $str] }
  779.     proc* { set res [ExpandProcname $str] }
  780.     var*  { set res [ExpandVariable $str] }
  781.     default {
  782.         set res {}
  783.         foreach t {Pathname Procname Variable} {
  784.         if {![catch {Expand$t $str} res] && ($res ne "")} { break }
  785.         }
  786.     }
  787.     }
  788.     set len [llength $res]
  789.     if {$len} {
  790.     set repl [lindex $res 0]
  791.     $w delete $tmp insert
  792.     $w insert $tmp $repl {input stdin}
  793.     if {($len > 1) && $::tk::console::showMatches && $repl eq $str} {
  794.         puts stdout [lsort [lreplace $res 0 0]]
  795.     }
  796.     } else { bell }
  797.     return [incr len -1]
  798. }
  799.  
  800. # ::tk::console::ExpandPathname --
  801. #
  802. # Expand a file pathname based on $str
  803. # This is based on UNIX file name conventions
  804. #
  805. # Arguments:
  806. #    str    - partial file pathname to expand
  807. #
  808. # Calls:    ::tk::console::ExpandBestMatch
  809. #
  810. # Returns:    list containing longest unique match followed by all the
  811. #        possible further matches
  812.  
  813. proc ::tk::console::ExpandPathname str {
  814.     set pwd [EvalAttached pwd]
  815.     if {[catch {EvalAttached [list cd [file dirname $str]]} err]} {
  816.     return -code error $err
  817.     }
  818.     set dir [file tail $str]
  819.     ## Check to see if it was known to be a directory and keep the trailing
  820.     ## slash if so (file tail cuts it off)
  821.     if {[string match */ $str]} { append dir / }
  822.     if {[catch {lsort [EvalAttached [list glob $dir*]]} m]} {
  823.     set match {}
  824.     } else {
  825.     if {[llength $m] > 1} {
  826.         global tcl_platform
  827.         if {[string match windows $tcl_platform(platform)]} {
  828.         ## Windows is screwy because it's case insensitive
  829.         set tmp [ExpandBestMatch [string tolower $m] \
  830.             [string tolower $dir]]
  831.         ## Don't change case if we haven't changed the word
  832.         if {[string length $dir]==[string length $tmp]} {
  833.             set tmp $dir
  834.         }
  835.         } else {
  836.         set tmp [ExpandBestMatch $m $dir]
  837.         }
  838.         if {[string match ?*/* $str]} {
  839.         set tmp [file dirname $str]/$tmp
  840.         } elseif {[string match /* $str]} {
  841.         set tmp /$tmp
  842.         }
  843.         regsub -all { } $tmp {\\ } tmp
  844.         set match [linsert $m 0 $tmp]
  845.     } else {
  846.         ## This may look goofy, but it handles spaces in path names
  847.         eval append match $m
  848.         if {[file isdir $match]} {append match /}
  849.         if {[string match ?*/* $str]} {
  850.         set match [file dirname $str]/$match
  851.         } elseif {[string match /* $str]} {
  852.         set match /$match
  853.         }
  854.         regsub -all { } $match {\\ } match
  855.         ## Why is this one needed and the ones below aren't!!
  856.         set match [list $match]
  857.     }
  858.     }
  859.     EvalAttached [list cd $pwd]
  860.     return $match
  861. }
  862.  
  863. # ::tk::console::ExpandProcname --
  864. #
  865. # Expand a tcl proc name based on $str
  866. #
  867. # Arguments:
  868. #    str    - partial proc name to expand
  869. #
  870. # Calls:    ::tk::console::ExpandBestMatch
  871. #
  872. # Returns:    list containing longest unique match followed by all the
  873. #        possible further matches
  874.  
  875. proc ::tk::console::ExpandProcname str {
  876.     set match [EvalAttached [list info commands $str*]]
  877.     if {[llength $match] == 0} {
  878.     set ns [EvalAttached \
  879.         "namespace children \[namespace current\] [list $str*]"]
  880.     if {[llength $ns]==1} {
  881.         set match [EvalAttached [list info commands ${ns}::*]]
  882.     } else {
  883.         set match $ns
  884.     }
  885.     }
  886.     if {[llength $match] > 1} {
  887.     regsub -all { } [ExpandBestMatch $match $str] {\\ } str
  888.     set match [linsert $match 0 $str]
  889.     } else {
  890.     regsub -all { } $match {\\ } match
  891.     }
  892.     return $match
  893. }
  894.  
  895. # ::tk::console::ExpandVariable --
  896. #
  897. # Expand a tcl variable name based on $str
  898. #
  899. # Arguments:
  900. #    str    - partial tcl var name to expand
  901. #
  902. # Calls:    ::tk::console::ExpandBestMatch
  903. #
  904. # Returns:    list containing longest unique match followed by all the
  905. #        possible further matches
  906.  
  907. proc ::tk::console::ExpandVariable str {
  908.     if {[regexp {([^\(]*)\((.*)} $str junk ary str]} {
  909.     ## Looks like they're trying to expand an array.
  910.     set match [EvalAttached [list array names $ary $str*]]
  911.     if {[llength $match] > 1} {
  912.         set vars $ary\([ExpandBestMatch $match $str]
  913.         foreach var $match {lappend vars $ary\($var\)}
  914.         return $vars
  915.     } elseif {[llength $match] == 1} {
  916.         set match $ary\($match\)
  917.     }
  918.     ## Space transformation avoided for array names.
  919.     } else {
  920.     set match [EvalAttached [list info vars $str*]]
  921.     if {[llength $match] > 1} {
  922.         regsub -all { } [ExpandBestMatch $match $str] {\\ } str
  923.         set match [linsert $match 0 $str]
  924.     } else {
  925.         regsub -all { } $match {\\ } match
  926.     }
  927.     }
  928.     return $match
  929. }
  930.  
  931. # ::tk::console::ExpandBestMatch --
  932. #
  933. # Finds the best unique match in a list of names.
  934. # The extra $e in this argument allows us to limit the innermost loop a little
  935. # further.  This improves speed as $l becomes large or $e becomes long.
  936. #
  937. # Arguments:
  938. #    l    - list to find best unique match in
  939. #     e    - currently best known unique match
  940. #
  941. # Returns:    longest unique match in the list
  942.  
  943. proc ::tk::console::ExpandBestMatch {l {e {}}} {
  944.     set ec [lindex $l 0]
  945.     if {[llength $l]>1} {
  946.     set e  [string length $e]; incr e -1
  947.     set ei [string length $ec]; incr ei -1
  948.     foreach l $l {
  949.         while {$ei>=$e && [string first $ec $l]} {
  950.         set ec [string range $ec 0 [incr ei -1]]
  951.         }
  952.     }
  953.     }
  954.     return $ec
  955. }
  956.  
  957. # now initialize the console
  958. ::tk::ConsoleInit 
  959.